Our Services

Our Works

Testimonials

What Our Clients
Say About Us

I am incredibly pleased with the services provided by Timedoor, Satya and team are very pleasant to work with. The team has proven to be efficient and empathetic. They delivered a fully functional website within timeframe and tailored an easy-to-use CMS. Throughout the entire process, I was consistently impressed with their attention to detail and problem solving.

Alvita Chen

Associate Director of SAKA Museum

Definitely the best IT company in Bali. For us it was very important to find professional company who will match our expectation and will be ready to create a functional and attractive website for us, we spent a few month choosing between 5 companies and made a right choice. Everyone in Timedoor is very passionate, experienced and ready to help anytime you need it.

Hugo

Founder of INDA SURF

Thank you for your such good assistance and support for our website. I trusted Timedoor Team since they have good working ethics and really care about their customer. They respond to our requests and questions immediately. I’m satisfied for the result and will surely ask for Timedoor Team’s care for my future projects. All success for Timedoor and team.

Chinatsu Ishiodori

Founder of Siki Bali & Rumah Kecil

We thank Timedoor Indonesia especially Mr. Yutaka and team who designed our Website and its system. PT. Timedoor Indonesia works professionally and always punctual with the time to finish every project they have. Now our daily work became easier because they built us the perfect website to fulfill all our request and needs. All the best for Timedoor Team.

Pipin Haryanto

General Manager of Oasis Kuta Hotel

At first time I met Timedoor Team I feel that I will have a good business relationship with them. Their team is professional and friendly. We have good communication so we trust Timedoor to do some projects, from a Hospitality site, Construction site, and even Educational Institution site. Our all old website reborn as new website.

Fatin Hamamah

Founder of Abhinaya Villa Management

I would like to thank all the professional team of Timedoor for creating an excellent website for my company. It is a real pleasure to work with them, excellent communication, reactivity and always bring solution with creativity. I am very satisfy with their services and I would recommend them without hesitation to anyone looking for a professional web services.

Furukawa Teito

Founder of Luxindo Property

It’s hard to find a good website developer who understand what we really want and need in Ineondsia. I work in Bali, Jakarta, and wanted to make a website which represents my business’ philosophy and concept, and Timedoor Indonesia delivered exactly what I imagined my website would be.

Till Marzloff

Architect of Tiga Kotak

Timedoor built a great new website for us 7South Coffee and we are very happy with the results. We plan to use Timedoor services again for our other new websites as we expand to more countries and for internet marketing. Their team is professional and fun to work with on these projects!

Lance Shay

Founder of 7 South Coffee

Other Happy Clients

Hino
Volkswagen
BNI
Indosat
Broco
Caroline
Shimajiro
Jiipe
LIA
Spin Fish
Bali TV
Bali Post
Asita
Mercure
Kura-Kura Bus
Bubba Gump
Siki
Watabe
Kamaya Bali
Tasini
Granola
Hideaway
Hundred Seeds
JAIF
J Trust Bank
Nissan
Sharp Point
Cow Style
Honda
Yamaha

Our Location

Bali

Jl. Tukad Yeh Aya IX No.46, Renon Denpasar, Bali

+62-812-3836-3440

Open Map

Jakarta

JL Boulevard Barat Raya Blok LC7. 39-40, Klp. Gading Bar., Daerah Khusus Ibukota Jakarta 14240

+628814677923

Open Map

New Cairo

٢٤ د جنوب الاكاديمية, New Cairo 3, Cairo Governorate, Egypt

+201551002308

Open Map

Tokyo

160-0004 Tokyo, Shinjuku, Yotsuya 3 Chome 2-1 Frontplace Yotsuya Building 2F

+62-812-3836-3440

Open Map

We are working across the world

Our Team

Why We Have a Strong Team

Timedoor's Team

Why We Have a Strong Team

PT. Timedoor Indonesia is one of the top IT company in Denpasar, Bali. Our CEO, Yutaka Tokunaga, grew up and was educated in Japan, which is famous for the hard working culture to provide top quality products or services. He is a professional business person with an extensive knowledge of internet business and is happy to use his knowledge to assist Timedoor clients in Indonesia.

Timedoor's Ceo Mr. Yutaka

Why We Are
Professional

I moved from Japan to Indonesia in 2014 and started this IT company. At that time, the speed of the Internet was slow and there were not many website and mobile app services, but over the last five years, the digitalization of Indonesia has progressed rapidly.

Timedoor Career

We Are Hiring New Talents!

Timedoor always welcome young talents who have great potential and passion. If you want to develop yourself and your career, Timedoor is the best place to start your career. We are looking for Web Programmers, Web Designer, Mobile Apps Developer as full time employee or Part Time Job.

Let's join our adventure!

Why Us?

Home About Image
Home About Image

Your shop and website share the same analogy. Customer will not visit your shop if they see the place dirty just like how they would leave immediately if they see your web is poorly designed. Our motto is: "Creating a User Friendly" website that makes it easy for customers to navigate.

Our Customer Support Team always responds promptly and sincerely to customers with the right answers, based on their extensive knowledge coordinated with management, designers and programmers. If you have any problem with our customer support, please immediately contact us. We aim to be a good partner that takes away stress and helps your business.

Do you want a Wordpress or PHP website? We can handle both as per your request. Our programmers are highly skilled professionals, who have been trained with Japanese standard. Even with difficult functions or huge systems, we are ready to challenge ourselves and overcome the obstacle. For every customer requests, we always look for solutions to realize results and propose ideas instead of looking for reasons on why we cannot do it.

One of our motto is ‘Create a website that contributes to the results of your business’. We are not just creating a website, we have the principle that every Website that is made will contribute to your business. We are committed to help your business thrive and grow.

News & Blog

Stay Updated
with Latest Trends

Monetizing React Native App: A Beginner’s Guide to Implementing In-App Purchases

March 30, 2024 •

Monetizing React Native App: A Beginner’s Guide to Implementing In-App Purchases

In-app purchase have become an integral part of monetization strategy, enabling the creators to generate revenue from their mobile app and also providing users with a seamless purchasing experience. Fortunately, both widely used mobile platforms, Android and iOS, have streamlined the In-App Purchase transaction & revenue distribution process through their app stores. But there aren’t many tutorial on internet about how to implementing it, especially in React Native. You can use paid In-App Purchase management platform such as Adapty or RevenueCat to simplifies the process, but this article will guide you through implementing In-App Purchase in React Native using Google Billing & Apple StoreKit APIs. We’ll also test it with sandbox account. What exactly is In-app Purchase ? In-app purchase is a feature provided by a platform to buy digital items or services directly from the mobile app. With In-app purchase feature, the creators are able to distribute their app for free with basics feature, but then offering the users an option to upgrade it to full feature. In-app purchase feature brings numerous benefits to both the creator and the user not only generating sustainable revenue for the creators, iap also encourage creators to provide a better user experience, update the content frequently to keep the users’s engagement. In-App Purchases Types There are three types of in-app purchase based on their usage Consumable Consumable is a type of In-App Purchases that allows users to buy and use digital items multiple times. These item is typically designed for one-time use but can be bought repeatedly. Consumable items can be virtual currencies like gold or diamond in games, extra health or points in a game, .etc. Non-Consumable Non-Consumable is the opposite of the consumable type, where users only need to purchased the digital items once and can use them indefinitely. Once users have purchased it, the item will linger to user’s account across different devices and app installations. The example of non-consumable in-app purchase includes ads Removal, pro version of an app, levels in game, .etc. Auto-Renewable Subscription Auto-Renewable Subscription is a type that enabled the users to purchase a service or content for a set of period. This type of item will renew automatically at the end of certain period unless cancelled by the user. For example, Access premium feature for a full week, month, or a year. Each In-app purchase type has a different requirement & implementation. In the next part this we will only focusing on the subscription-based type in React Native. In-App Purchase Prerequisite Before diving into implementation, it’s imperative to adhere to certain prerequisites. Initially, signing up to developer account for both Android and iOS platforms is essential if we are targeting these platforms. This enables us to create the items or products that we intend to offer within our application. Android Play Console Setup On Android, it's essential to create a payment profile. To do this, navigate to the Payment Settings within the Play Console, then click "Create Payments Profile" and ensure all information provided is accurate. Once the payment profile is created, you can link your bank account to receive revenue shares from Google's In-App Purchases. With this in place, you can proceed to create your In-App Purchase items. Simply access your app in the Play Console, navigate to the Monetize section in the left panel, and select your desired In-App Purchase type. Follow the instructions provided on the page, and you'll be able to create your first In-App Purchase item effortlessly. iOS Play Console Setup On iOS is quite similar to the process on Android. You'll need to configure your bank account to receive revenue generated from your app. Begin by accessing your App Store Connect website. Navigate to the Agreements tab, locate the row for paid apps, and select "Set Up Tax and Banking." On this page, input your bank account details, ensuring all required fields are filled accurately, and check the "I have read" checkbox. Finally, save your changes. Once the bank account is set up, you can proceed to create the In-App Purchase (IAP) items. To do this, navigate to your app within the My Apps menu. In the left panel, select your desired in-app purchase type, whether it's consumable, non-consumable, or subscription-based. IAP Implementation in React Native To set up in-app purchases in React Native, we utilize the Google Billing APIs and/or the Apple StoreKit APIs. Instead of creating separate native modules for each platform, we can streamline the process with the react-native-iap library. It offers a unified interface for managing purchases across both the Google Play Store and the Apple App Store. Under the hood, React Native IAP leverages native APIs from Google and Apple to handle purchase flows, verify transactions, and manage subscriptions. By using React Native IAP, developers gain access to a consistent set of methods and events, regardless of the platform, facilitating easier implementation and maintenance of in-app purchases in cross-platform React Native apps. To install react-native-iap library run this code npm install react-native-iap # or yarn add react-native-iap Setup for iOS, if you’are targetting to iOS platform cd ios pod install cd .. react-native-iap library provide us a hooks to simplifies the fetching item, making purchase, and handle purchasing process so let’s use that. import { withIAPContext, useIAP } from 'react-native-iap' const SubscriptionScreen = () => { const { connected, subscriptions, products, getSubscriptions, getProducts, currentPurchase, currentPurchaseError, } = useIAP(); return <> {/* your component */} </> } export default withIAPContext(SubscriptionScreen) Let’s retrieve the earlier created IAP item. First we need to declare the Product ID’s : const items = Platform.select({ ios: ["com_example_product1ios", "com_example_product2ios", "com_example_product3ios"], android: ["com_example_product1", "com_example_product2", "com_example_product3"], }); if the product is subscription use getSubscriptions method : if the product is not a subscription, you can use getProducts method: useEffect(() => { if (connected) { handleGetSubscription() } }, [connected]); const handleGetSubscription = async () => { try { //show loading animation await getSubscriptions({ skus: items! }); //hide loading animation } catch (e) { //handle error fetching } } If the fetching method is success, the subscriptions or products variable will be populated asynchronously, so you can display the your offered products on the screen : <FlatList data={subscriptions} style={{ flex: 1, marginTop: 8 }} scrollEnabled={false} keyExtractor={(item, index) => `index ${index}`} renderItem = {({item,index}) => { {/* showing product name and it's price */} <Text>{Platform.OS == 'ios' ? item.title : item.name} <Text>{Platform.OS == 'ios' ? item.localizedPrice : item.subscriptionOfferDetails[0].pricingPhases.pricingPhaseList[item.subscriptionOfferDetails[0].pricingPhases.pricingPhaseList.length - 1].formattedPrice}</Text> }} /> To make purchase we can use requestSubscription or requestPurchase depending on your product type. //if subscription use this const handlePurchase = async(item) => { if (Platform.OS == "ios") { await requestSubscription({ sku: item.productId }); } else { await requestSubscription({ subscriptionOffers: [{ sku: item.productId, offerToken: item.subscriptionOfferDetails[0].offerToken }] }); } } //if consumable or non-consumable product use this const handlePurchase = async(item) => { await requestPurchase({sku: item.productId}) } After making a purchase, we can observe the purchase events. The variables currentPurchase and currentPurchaseError will be updated based on the result of the purchase event. useEffect(() => { const checkCurrentPurchase = async (purchase) => { if(purchase){ //handle the purchase event //... //at the end, finish the current transaction try { const ackResult = await finishTransaction(purchase); console.log('ackResult', ackResult); } catch (ackErr) { console.warn('ackErr', ackErr); } } } checkCurrentPurchase(currentPurchase); }, [currentPurchaseError]); useEffect(() => { if (currentPurchaseError) { //handle error event } }, [currentPurchaseError]); Finally, the In-App Purchase integration is complete, and it's now ready for testing. Testing In-App Purchases Before publishing the app to public, it’s very important to thoroughly test it’s functionality in a controlled environment. Both Apple & Google offer sandbox environment for developers to test the in-app purchase feature without actually making real payments. Apple with sandbox account Conducting testing for an iOS app can be done by uploading the app into testflight and subsequently create sandbox account in your appstoreconnect console to facilitate simulated purchases. While this process may seems simple, but it’s actually not that simple. The testflight app may not accurately detect or incorporate the previously created sandbox account. Instead, it might utilize your actual Apple ID, leading to complications. This issue prevents access to sandbox account settings, crucial for tasks such as canceling or resetting the eligibility of your app's subscription—an essential feature for expediting the testing process. Following an extensive investigation on various forums and sources, I've discovered a workaround to resolve the issue. To implement this solution, start by signing out of your Apple ID from the App Store App. Next, open your app and activate the purchase paywall. A login form dialog will then appear on the screen; input your previously created sandbox account. The purchase paywall will promptly detect your sandbox account and finalize the purchase process. A success dialog will appear, allowing you to subsequently access the sandbox account settings to manage your app's subscription. To access sandbox account setting, open the Settings app, navigate to App Store section, scroll to the very bottom, and locate the sandbox account section. Tap on Apple ID or “Sign In” button, and then select “Manage”. Android with license testing account Contrary to iOS app testing, Android testing is notably straightforward and simple to set up. The process involves registering the tester's email into the license tester list in the Play Console. To achieve this, open the Play Console dashboard, navigate to the Setup menu on the left side panel, and select the License Testing submenu. If you haven't created a license tester list yet, you'll need to do so. Additionally, you have the option to specify subscription response scenarios, indicating whether it's a success, failure, or error. Once the email is registered in the license tester, you can seamlessly test the subscription without any complications. Pro-tip Note When developing & testing In-App Purchase, some issues may arise. Consequently, it is essential to consider certain key factors. Explore Every Possible ScenarioWhen testing IAP make sure to test various scenarios, including successful purchase, failure, cancelled, .etc. Handle Transaction Receipt on your own backend.Handling transaction receipt validation on your backend is highly recommended. This ensures that all purchases are verified and authenticated, mitigating the risk of fraudulent transactions. Moreover, implementing receipt validation on your backend provides greater control and flexibility in managing subscriptions, tracking user purchases, and regulating access to premium content or features. Validation of duplicated Transaction IDsWhen user subscribes or make purchases, the transaction will linked to their Google or Apple account. This connection may lead to information leaks if the backend system fails to validate duplicated transaction IDs when users create multiple accounts for the app. Unpublished app will persist in the sandbox environment.When the app is uploaded to TestFlight, Internal, or Closed Test, it will persist within the Apple or Google sandbox server URL, irrespective of the app's environment being configured as production. In instances where the app's environment is marked as production, then a user makes a purchase, the webhook notification will be sent to sandbox server url instead of the designated production url. This situation will leads to false production purchases. This is why backend should have validation to address this issue. Conclusion In-App Purchase has been proved as the most effective monetization method for creators to generate revenue while delivering significant value to users. Although implementing In-App Purchase in React Native may initially appear challenging and require numerous trial and error attempts, following best practices enables creators to seamlessly integrate it and provide an optimal user experience. Thank you for taking the time to read! if you have any further inquiries or wish to delve deeper into this topic, feel free to reach out to us via our website or through our various social media channels. Wishing you a fantastic journey in your programming endeavors!

Creating a Match Card Transition Animation for a Dating App: A Guide

March 6, 2024 • Knowledge

Creating a Match Card Transition Animation for a Dating App: A Guide

In the dynamic world of mobile applications, user engagement plays a crucial role, especially in dating apps. One effective way to enhance user interaction is by incorporating a Card Transition Animation. In this article, we'll delve into the process of creating a Card Transition Animation for a dating app using React Native and Reanimated.   Introduction Card Transition Animations are visually appealing and provide a seamless way for users to navigate through potential matches. Unlike traditional swipe gestures, this animation is triggered by a button press, leading to a smooth transition between different user profiles or cards. We will be using React Native, a popular framework for building mobile applications, and Reanimated, a library for handling complex animations.   Setting the Stage: Project Setup Before diving into the implementation of the Card Transition Animation, let's ensure that our development environment is set up correctly. Assuming you have a React Native project ready, ensure that you have the necessary dependencies installed. # Install Reanimated library npm install react-native-reanimated react-native-gesture-handler   Setting Up the Component In the dating app, we have two key components involved in the Card Transition Animation: PotentialMatchList and PotentialMatchItem. The former is responsible for rendering a list of potential matches, while the latter represents an individual match item.   PotentialMatchList Component The PotentialMatchList component serves as the container for the cards and handles user actions, passing relevant data to the PotentialMatchItem component.   // PotentialMatchList Component import React, { useMemo } from "react"; import PotentialMatchItem from "./PotentialMatchItem"; interface Props { // Props declaration } export default function PotentialMatchList({ // Props destructuring }: Props) { // ... return ( {slicedPotentialMatchList?.map((item, index) => { ); })} );   PotentialMatchItem Component The PotentialMatchItem component represents an individual match item and includes the Card Transition Animation logic. // Import necessary React and React Native components import React from "react"; import { View, TouchableOpacity, Text, Animated, Dimensions, StyleSheet, } from "react-native"; // Define the Props interface interface Props { onAnimate: () => void; } const PotentialMatchItem: React.FC = ({ onAnimate }) => { const translateXAnimateValue = new Animated.Value(0); const handleAnimate = (direction: string) => { const DURATION = 500; // Define the animations using Animated.parallel const animations = [ Animated.timing(translateXAnimateValue, { toValue: direction === "left" ? -1 : 1, duration: DURATION, useNativeDriver: true, }), Animated.timing(opacity, { toValue: 0, duration: DURATION, useNativeDriver: true, }), ]; // Start the animations in parallel Animated.parallel(animations).start(() => { console.log("Card slide..."); // Additional actions can be performed after the animation completes }); }; return ( {/* Your card content goes here */} Card Content {/* Button inside the Animated View */} handleAnimate("left")} style={styles.animateButton}> Animate ); }; const styles = StyleSheet.create({ container: { alignItems: "center", justifyContent: "center", marginBottom: 20, }, cardText: { fontSize: 20, fontWeight: "bold", marginBottom: 10, }, animateButton: { backgroundColor: "#3498db", padding: 10, borderRadius: 5, marginTop: 10, }, buttonText: { color: "white", fontWeight: "bold", textAlign: "center", }, animatedCard: { backgroundColor: "#2ecc71", padding: 20, borderRadius: 10, position: "absolute", top: 0, left: 0, }, }); export default PotentialMatchItem; The direction parameter is used to determine the direction of the animation. If direction is "left," it implies a dislike animation; otherwise, it implies a like animation. The animations are defined using AnimatedRN.timing for translation and opacity. Both animations are started in parallel using AnimatedRN.parallel. The completion callback of start can be used to perform additional actions after the animation completes.   Conclusion Implementing a Card Transition Animation for a dating app involves orchestrating various elements, from handling user button presses to animating background opacity and horizontal translation. React Native, coupled with the Reanimated library, provides a robust foundation for creating immersive animations that enhance the overall user experience. By following this guide, you can create a Card Transition Animation that not only adds a visual flair to your dating app but also ensures a delightful and engaging user journey. Experiment with different animation parameters and styles to tailor the card transition experience to your app's unique personality. Happy coding!

Designing UI Using Design Token with Figma Variables

November 23, 2023 • Knowledge, Figma

Designing UI Using Design Token with Figma Variables

Recently, Figma has released a major update that makes it easier for designers to create more flexible designs. If you are already familiar with it, the most talked-about feature is Variables. In the summer of 2023, Figma announced its latest feature, Figma Variables, which is similar to the function of design tokens and can be used directly in Figma. Figma Variables is currently in the Beta testing phase and is only available if you are on an educational or paid plan. This article will discuss how we use Variables and design tokens to make color usage more effective in design. Let's go!   Context & Problem We have a multi-brand design system that we use to design mobile applications. All styles from the brands are incorporated into one design called Timedoor Design System. When we initially created this design system, we did not consider making a flexible color system for different brands. However, after studying several famous design systems such as Material, IBM, and Ant Design System, we discovered that one of the fundamental elements to start a design system is to have a strong foundation, one of which is Design Tokens. Therefore, we have decided to create design tokens for the Timedoor Design System to simplify its usage, starting with Design Token Color.   Color Token Structure In the migration towards variables in Figma, we start by defining the color structure that will be used for all brands designed using the design system.   1. Primitive Tokens Primitive tokens are a collection of raw colors that will later be incorporated into semantic tokens. Examples of primitive tokens in colors are blue, purple, or green. We select several colors to be used as examples based on their function and brand colors. We create a primitives token structure with a shades structure as shown below, where a single raw color will be transformed into 11 derivative colors to facilitate the use of colors in the semantic scheme to be created.   2. Semantic Tokens Semantic tokens are a collection of variables that provide functionality to primitive tokens. Primitive tokens will reference each semantic token as needed. Examples of semantic tokens include primary color, secondary color, success color, and others. In the Timedoor Design System, we group semantic colors according to their functions, such as primary color, secondary color, background color, text color, and so on, as shown in the example below. As can be seen, primitive colors will be reused in semantic colors to maintain color consistency in design. In these semantic tokens, we also directly define themes, namely light and dark themes, both of which still use the same primitive color sources.   3. Contextual Tokens (Optional) Contextual tokens are usually used directly in the UI components being created. However, in the Timedoor Design System, we have decided to only use them up to semantic tokens, considering time and the number of people in the team. Contextual tokens will reuse the previously defined semantic colors. Examples of using contextual tokens include button-primary-default, button-primary-hover, and others.   How variables work in our design system Let's see how to apply color variables in the multi-brand design system that our team has created.   1. We separate the color file from the component file Separating files in the design system is useful for improving the efficiency of using colors, making it easier to update if there are any required updates to color variables or the components themselves. After separating the files, the color files will be published so that they can be used independently by the component files later.   2. Using color variables in components Example of using color token variables in a button component. The button container uses the color primary/main and the content inside uses the color primary/content. [caption id="attachment_6283" align="alignnone" width="768"] Example using color token in button component[/caption]   3. Components that already use semantic color tokens can utilize modes In semantic token, we have set it up so that designs that use color variables can change color according to the created modes, namely light and dark. Here is an example of using a color theme on a button component. [caption id="attachment_6284" align="alignnone" width="768"] Button component on light mode[/caption] [caption id="attachment_6287" align="alignnone" width="768"] Button component on dark mode[/caption]   In both of the above modes, the button component still uses the same semantic tokens, which are primary/main and primary/content. However, due to the different modes, the primitive token changes, making the design more flexible in terms of color usage.   Example using color token variables on our project One of the use cases of variables in our project is where we have 3 themes that already use primitive tokens and semantic tokens.   Conclusion Building a well-structured design system takes time and continuous iteration. Therefore, we try to establish a strong foundation in the design system we are building by applying design tokens through the variables feature in Figma. So don't be afraid to experiment so that we can learn from those experiments that have already happened in our design system. Thank you for reading. If you have any more questions or want to go deeper into this topic, just reach us via our website or another social links. Happy designing!

Testing